﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using FlowBasisSampleSite.Domain.Entities;
using FlowBasisSampleSite.Domain;
using FlowBasis.Data;
using System.Net;
using FlowBasis.Web.Mvc;
using System.Collections;
using FlowBasis.Json;
using FlowBasis.Security;


namespace FlowBasisSampleSite.Areas.Admin.Controllers
{
    [UserAuthorize(RequiredPermissions = new[] { FlowBasis.Security.BasicPermissions.SiteAdmin })]
    public class UserAccountsController : Controller
    {
        private IUserContextService userContextService;
        private IDataService dataService;
        private Func<IUnitOfWork> unitOfWorkFactory;

        public UserAccountsController(
            IUserContextService userContextService, 
            IDataService dataService,
            Func<IUnitOfWork> unitOfWorkFactory)
        {
            this.userContextService = userContextService;
            this.dataService = dataService;
            this.unitOfWorkFactory = unitOfWorkFactory;
        }

        public ActionResult Index()
        {
            return View();
        }

        public ActionResult Info(int id)
        {
            UserAccount userAccount = this.dataService.GetAll<UserAccount>().FirstOrDefault(ua => ua.UserAccountId == id);
            if (userAccount == null)
            {
                return new HttpStatusCodeResult((int)HttpStatusCode.NotFound);
            }

            ViewBag.UserAccount = userAccount;

            return View();
        }



        [PostRpc]
        public ActionResult DeleteUserAccount(int id)
        {
            if (this.userContextService.UserId.Equals(id))
            {
                throw new Exception("Unable to delete own account.");
            }

            var unitOfWork = this.unitOfWorkFactory();
            
            var userAccount = unitOfWork.GetAll<UserAccount>().SingleOrDefault(ua => ua.UserAccountId == id);
            if (userAccount == null)
            {
                throw new Exception("User account not found: " + id);
            }

            userAccount.IsDeleted = true;

            unitOfWork.Commit();

            return new PostRpcResult(true);
        }


        [PostRpc]
        public ActionResult UndeleteUserAccount(int id)
        {
            var unitOfWork = this.unitOfWorkFactory();

            var userAccount = unitOfWork.GetAll<UserAccount>().SingleOrDefault(ua => ua.UserAccountId == id);
            if (userAccount == null)
            {
                throw new Exception("User account not found: " + id);
            }

            userAccount.IsDeleted = false;

            unitOfWork.Commit();

            return new PostRpcResult(true);
        }

        
        [PostRpc]
        public ActionResult GetUserList(
            UserQuery query,
            int? offset, 
            int? maxResults)
        {                        
            if (query == null)            
                query = new UserQuery();            

            IQueryable<UserAccount> userAccountsQuery = this.dataService.GetAll<UserAccount>();

            if (!String.IsNullOrWhiteSpace(query.MatchText))
            {
                string matchText = query.MatchText.Trim();

                userAccountsQuery = userAccountsQuery.Where(ua =>
                    ua.DisplayName.Contains(matchText) || ua.PrimaryEmail.Contains(matchText));
            }

            if (!query.IncludeDeleted)
            {
                userAccountsQuery = userAccountsQuery.Where(ua => !ua.IsDeleted);
            }
                    
            userAccountsQuery = userAccountsQuery.OrderBy(ua => ua.DisplayName);

            var resultSet = userAccountsQuery.ToJObjectResultSet(
                offset, maxResults,
                (userAccount) =>
                {
                    dynamic userData = new JObject();
                    userData.id = userAccount.UserAccountId;
                    userData.displayName = userAccount.DisplayName;
                    userData.primaryEmail = userAccount.PrimaryEmail;

                    if (userAccount.IsDeleted)
                        userData.isDeleted = true;

                    return userData;
                });

            return new PostRpcResult(resultSet);
        }


        public class UserQuery
        {            
            public string MatchText { get; set; }            
            public bool IncludeDeleted { get; set; }
        }
    }
}